package com.boat.starter.web.excepton;

import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.boat.framework.base.api.Response;
import com.boat.framework.base.exception.CommonErrorCode;
import com.boat.framework.base.exception.ErrorCodeUtils;
import com.boat.framework.base.exception.ServiceException;
import com.boat.framework.common.monitor.event.ControllerCallFailed;
import com.boat.framework.common.monitor.logs.EventLog;

import lombok.extern.slf4j.Slf4j;

/**
 * 全局异常处理器
 * 
 * @author 周江
 *
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
	
	@ExceptionHandler(value = Exception.class)
	public Response<Void> errorHandler(Exception ex) {
		Response<Void> response = convExceptionResponse(ex);
		
		if(ErrorCodeUtils.isNoPrintStack(response.getCode())) {
			//为避免日志太多，业务异常，不打印堆栈信息
			log.warn("接口调用出错，错误原因:" + ex.getMessage());
		}else {
			log.warn("接口调用出错，错误原因:" + ex.getMessage(), ex);
		}
		
		return response;
	}
	
	public static Response<Void> convExceptionResponse(Throwable ex) {
		Response<Void> response = new Response<>();
		if (ex instanceof ServiceException) {
			ServiceException se = (ServiceException) ex;
			response.setCode(se.getCode());
			response.setMessage(se.getMessage());
		} else if (ex instanceof MethodArgumentNotValidException) {
			//参数校验异常
			MethodArgumentNotValidException me = (MethodArgumentNotValidException) ex;
			String errMsg = null;
			// 如果底层抛出了此异常，这个getErrorCount一定会>0
			if (me.getBindingResult().getErrorCount() > 0) {
				errMsg = me.getBindingResult().getAllErrors().get(0).getDefaultMessage();
			}
			response.setCode(CommonErrorCode.INVALID_PARAMETER.getCode());
			response.setMessage(CommonErrorCode.INVALID_PARAMETER.getMessage(new String[] { errMsg }));
		} else if(ex instanceof IllegalArgumentException) {
			//参数无效
			IllegalArgumentException iex = (IllegalArgumentException) ex;
			response.setCode(CommonErrorCode.INVALID_PARAMETER.getCode());
			response.setMessage(CommonErrorCode.INVALID_PARAMETER.getMessage(new String[] { iex.getMessage() }));
		} else {
			response.setCode(CommonErrorCode.SYSTEM_ERROR.getCode());
			response.setMessage(CommonErrorCode.SYSTEM_ERROR.getMessage());
		}
		
		//记录监控日志
		EventLog.log(new ControllerCallFailed(ex, response));
		
		return response;
	}
}
